#pragma once

#include "Defs.h"
#include "IntegrableInterface.h"
#include "Shape.h"

namespace PHYOgre
{


class RigidBody :  public IntegrableInterface
{
public:
	RigidBody(void);
	~RigidBody(void);

	//--------------------IntegrableInterface ---------------------------------
	void Integrate(const Real& iDt);
	void AddForce(const Vector3& iForce);
	void AddForceAtBodyPoint(const Vector3& iForceWorldSpace, const Vector3& iPointLocalSpace);
	void AddForceAtPoint(const Vector3& iForceWorldSpace, const Vector3& iPointWorldSpace);
	void ClearForceAccumulator();
	
	void SetNode(Ogre::Node *iNode);

	void CalculateDerivedData();
	void SetInertialTensor(const Matrix3& iTensor);

	void SetMass(const Real& iMass);
	void SetInverseMass(const Real& iInverseMass);
	bool HasFiniteMass()const;

	void SetShape(Shape* iShape);
	const Shape* GetShape() const;
	void SetPosition(const Vector3& iPosition);
	Real GetInverseMass()const;
	Vector3 GetVelocity()const;
	Vector3 GetPosition()const;

	//----------MATERIAL PROPERTIES ------------
	void SetFriction(const Real& iFriction);
	void SetRestitution(const Real& iRestitution);

	Real GetRestitution() const;
	Real GetFriction() const;

	const Ogre::Sphere& GetBoundingSphere() const;
	const Ogre::MovableObject& GetObject() const;


private:

	void UpdateInertialTensorWorld();

	//---------------- properties ---------------------
	Vector3 mVelocity;
	Vector3 mAngularVelocity;

	Vector3 mAcceleration;
	Vector3 mLastFrameAcceleration;

	Real mInverseMass;

	Vector3 mForceAccumulator;
	Vector3 mTorqueAccumulator;

	Matrix3 mInverseInertialTensor;
	Matrix3 mInverseInertialTensorWorld;

	Real mLinearDampling;
	Real mAngularDampling;

	//-------------- MATERIAL ---------------------
	Real mFriction;
	Real mRestitution;

	Ogre::Node *mNode;
	Ogre::MovableObject *mObject;
	Shape *mShape;
};
}
